/*!
   \file XmlImpl.cpp
 *
   \date Jan 6, 2009
   \author Sarah Smith <sez@storybridge.org>
 *
   \brief Template implementations for Xml helpers.
   \details This file is included at the bottom of Xml.h.
 */

#include <QTextStream>
#include <QStringList>

/*!
   \brief Append the tag \a tagName to the data in \a xml.
   \details Xml helper function to create a data tag.  The data item \a value
   must be of a type \a T which supports the << and >> QTextStream operators.
   The \a tagName must be unique in the Xml document.
   \param xml the Xml data object to append the tag to.
   \param tagName the name for the tag.
   \param value the data item to add.
   \tparam T type of the value being added.
   \relates Xml
 */
template <typename T>
void appendTag(Xml &xml, const QString &tagName, const T &value)
{
    QString result;
    {
        QTextStream out(&result);
        out << value;
    }
    xml.appendTag(tagName, result);
}

/*!
   \brief Append the tag array \a tagName to the data in \a xml.
   \details Xml helper function to create a data array.  The array is contained by
   a tag named \a tagName.  The data item \a value
   must be of a type \a T which supports the << and >> QTextStream operators.
   The \a tagName must be unique in the Xml document.
   \param xml the Xml data object to append the tag to.
   \param tagName the name for the tag.
   \param values a QList<\a T> of the data items to add.
   \tparam T type of the value being added.
   \relates Xml
 */
template <typename T>
void appendArray(Xml &xml, const QString &tagName, const QList<T> &values)
{
    QStringList data;
    for (int i = 0; i < values.size(); ++i)
    {
        QString result;
        {
            QTextStream out(&result);
            out << values.at(i);
        }
    }
    xml.appendArray(tagName, data);
}

/*!
   \brief Retrieve the data named \a tagName from \a xml.
   \details Xml helper function to retrieve data.  The data is contained by
   a tag named \a key.  The data items expected
   must be of a type \a T which supports the << and >> QTextStream operators.
   The \a key must be unique in the Xml document.
   Dont use this method for QString instead just call xml.value(key) directly,
   since streaming out the QString will only get the first token.
   \param xml the Xml data object to retrieve the tag from.
   \param key the name for the tag.
   \return <\a T> data items.
   \tparam T type of the value being retrieved.
   \relates Xml
 */
template <typename T>
T value(const Xml &xml, const QString &key)
{
    QString data = xml.value(key);
    T result;
    QTextStream in(&data);
    in >> result;
    return result;
}

/*!
   \brief Retrieve the data array cotained in \a tagName from \a xml.
   \details Xml helper function to retrieve data.  The data is contained by
   a tag named \a key.  The data items expected
   must be of a type \a T which supports the << and >> QTextStream operators.
   The \a key must be unique in the Xml document.
   Dont use this method for QString instead just call xml.valueArray(key) directly,
   since streaming out the QString will only get the first token of each item.
   \param xml the Xml data object to retrieve the tag from.
   \param key the name for the tag.
   \return QList<\a T> of the data items.
   \tparam T type of the value being retrieved.
   \relates Xml
 */
template <typename T>
QList<T> valueArray(const Xml &xml, const QString &key)
{
    QList<T> results;
    QStringList array = xml.valueArray(key);
    for (int index = 0; index < array.size(); ++index)
    {
        T result;
        QString data = array.at(index);
        QTextStream in(&data);
        in >> result;
        results << result;
    }
    return results;
}

/*!
   \brief Append the tag array \a tagName to the titled data in \a xml.
   \details Xml helper function to create a titled data array.  The array is
   contained by a tag named \a tagName.  Each item in the array is an item
   inheriting TitledData().  The array created first serializes the titled
   data items, then stores the titles in a value array in the Xml.
   The \a tagName must be unique in the Xml document.
   \param xml the Xml data object to append the tag to.
   \param tagName the name for the tag.
   \param list a QList<\a T> of the titled data items to add.
   \tparam T type of the titled data being added.
   \relates Xml
 */
template <typename T>
void appendTitleArray(Xml &xml, const QString &tagName, const QList<T> &list)
{
    QStringList results;
    for (int i = 0; i < list.size(); ++i)
    {
        T t = list[i];
        t.saveToXml();
        results << t.title();
    }
    xml.appendArray(tagName, results);
}

/*!
   \brief Retrieve the titled data array contained in \a tagName from \a xml.
   \details Xml helper function to retrieve titled data.  The data is contained by
   a tag named \a tagName.  The data items are all of a type \a T which inherits
   from TitledData().  The data is deserialized, using the titles and types stored
   in the Xml value array, and loaded into a QList<\a T>
   The \a tagName must be unique in the Xml document.
   \param xml the Xml data object to retrieve the tag from.
   \param tagName the name for the tag.
   \return QList<\a T> of the data items.
   \tparam T type of the value being retrieved.
   \relates Xml
 */
template <typename T>
QList<T> valueTitleArray(const Xml &xml, const QString &tagName)
{
    QList<T> results;
    QStringList listNames = xml.valueArray(tagName);
    QStringList::const_iterator it = listNames.begin();
    for ( ; it != listNames.end(); ++it)
    {
        T t(*it);
        t.loadFromXml();
        results << t;
    }
    return results;
}
